package com.jiangyifen.robot.sdkserver;

import java.net.InetSocketAddress;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jiangyifen.robot.consts.ErrCode;
import com.jiangyifen.robot.sdk.response.BaseResponse;
import com.jiangyifen.robot.sdkserver.requesthandler.AbstractRequestHandler;
import com.jiangyifen.robot.sdkserver.requesthandler.HandlerMap;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

@Component
public class RobotSdkServerHandler extends SimpleChannelInboundHandler<String> {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Override
	public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
		logger.debug("recv from client: {}", msg);

		if (StringUtils.isBlank(msg)) {
			logger.error("BLANK MSG");
			return;
		}

		if ("PONG".equals(msg)) {
			// 处理 心跳, do nothing
		} else if (msg.contains("requestName")) {
			// 处理 request
			BaseResponse<?> response = handleRequest(ctx, msg);

			// 对于新建的连接，首次发起消息应该是认证消息
			// 对于认证失败的，直接关闭channel；对于认证成功的，hold住该连接供后续使用。
			if (!RobotSdkServer.channels.contains(ctx.channel())) {
				if (response.getErrCode().equals(ErrCode.AUTHENTICATION_FAIL.getErrcode())) {
					InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
					String clientIp = insocket.getAddress().getHostAddress();
					logger.error("{}, clientIp={}", ErrCode.AUTHENTICATION_FAIL.getErrmsg(), clientIp);
					ctx.close();
					return;
				} else {
					RobotSdkServer.channels.add(ctx.channel());
					logger.info("channels.size()={}", RobotSdkServer.channels.size());
				}
			}
			
			ctx.writeAndFlush(JSON.toJSONString(response) + "\r\n");

		}

	}

	@Override
	public void channelActive(final ChannelHandlerContext ctx) {
		// RobotSdkServer.channels.add(ctx.channel());
		// logger.info("channels.size()={}", RobotSdkServer.channels.size());
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		logger.info("channelInactive");
		logger.info("channels.size()={}", RobotSdkServer.channels.size());
	}

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		super.userEventTriggered(ctx, evt);

		if (evt instanceof IdleStateEvent) {

			IdleStateEvent event = (IdleStateEvent) evt;

			if (event.state().equals(IdleState.READER_IDLE)) {
				ctx.writeAndFlush("PING\r\n");

			} else if (event.state().equals(IdleState.WRITER_IDLE)) {
				ctx.writeAndFlush("PING\r\n");

			} else if (event.state().equals(IdleState.ALL_IDLE)) {
				// 未进行读写
				// 超时关闭channel
				System.out.println("IdleState.ALL_IDLE!! ctx.close()");
				ctx.close();
			}
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		logger.error(cause.getMessage(), cause);
		ctx.close();
	}

	private BaseResponse<?> handleRequest(ChannelHandlerContext ctx, String requestString) {
		JSONObject json = JSON.parseObject(requestString);
		String requestName = json.getString("requestName");
		AbstractRequestHandler<?> handler = HandlerMap.handlerMap.get(requestName);
		String requestId = json.getString("id");
		String requestBody = json.getString("body");

		if (handler == null) {
			String errMsg = "没有实现的request：" + requestName;
			logger.error(errMsg);
			return BaseResponse.FAIL(requestId, null, "-1", errMsg);
		}

		return handler.handle(ctx, requestId, requestBody);
	}
}